package report

import (
	"fmt"
	"github.com/spf13/cast"
	"longmen/server/config/global"
	"longmen/server/pkg/common/helper/timehelper"
	"longmen/server/pkg/db/mysql/models/models_report"
	"time"
)

const (
	ReportImBatchSendCacheKey     = "REPORT:IM_BATCHSEND:%d"      //发送
	ReportImBatchReadCacheKey     = "REPORT:IM_BATCHREAD:%d"      //读取
	ReportImBatchReplyCacheKey    = "REPORT:IM_BATCHREPLY:%d"     //回复
	ReportImEveryTimeSendCachekey = "REPORT:IM_EVERYTIME_SEND:%d" //每次发送数
	KeyExpire                     = 172800
)

type imReport struct {
	batchSendNum int //批量发送数
	batchReadNum int //批量发送对应的阅读数
}

func NewImReport() *imReport {
	return &imReport{}
}

func (s *imReport) IncrBatchSendNum(uid string) error {
	key := fmt.Sprintf(ReportImBatchSendCacheKey, timehelper.Midnight())
	b := global.GetRds().Exists(key).Val()
	err := global.GetRds().HIncrBy(key, uid, 1).Err()
	if b == 0 {
		global.GetRds().Expire(key, time.Second*time.Duration(KeyExpire)).Result()
	}
	return err
}

func (s *imReport) IncrBatchEveryTimeSendNum(num int64) error {
	key := fmt.Sprintf(ReportImEveryTimeSendCachekey, timehelper.Midnight())
	b := global.GetRds().Exists(key).Val()
	err := global.GetRds().HIncrBy(key, cast.ToString(time.Now().Unix()), num).Err()
	if b == 0 {
		global.GetRds().Expire(key, time.Second*time.Duration(KeyExpire)).Result()
	}
	return err
}

func (s *imReport) IncrBatchReadNum(uid string) error {
	batchSendNumKey := fmt.Sprintf(ReportImBatchSendCacheKey, timehelper.Midnight())
	e := global.GetRds().HGet(batchSendNumKey, uid).Val()
	if e == "" {
		return nil
	}

	key := fmt.Sprintf(ReportImBatchReadCacheKey, timehelper.Midnight())
	b := global.GetRds().Exists(key).Val()
	err := global.GetRds().HIncrBy(key, uid, 1).Err()
	if b == 0 {
		global.GetRds().Expire(key, time.Second*time.Duration(KeyExpire))
	}
	return err
}

func (s *imReport) IncrBatchReplyNum(uid string) error {
	key := fmt.Sprintf(ReportImBatchReplyCacheKey, timehelper.Midnight())
	b := global.GetRds().Exists(key).Val()
	err := global.GetRds().HIncrBy(key, uid, 1).Err()
	if b == 0 {
		global.GetRds().Expire(key, time.Second*time.Duration(KeyExpire))
	}
	return err

}

func (s *imReport) InsertDB() error {
	midnight := timehelper.Midnight()
	key := fmt.Sprintf(ReportImBatchSendCacheKey, midnight)
	batchSendNum, err := global.GetRds().HLen(key).Result()
	global.Log.Debugf("batchSendNum :%v", batchSendNum)
	if err != nil {
		global.Log.Errorf("IMREPORT InsertDB err:%v", err)
	}
	key = fmt.Sprintf(ReportImBatchReadCacheKey, midnight)
	batchReadNum, err := global.GetRds().HLen(key).Result()
	if err != nil {
		global.Log.Errorf("IMREPORT InsertDB err:%v", err)
	}
	key = fmt.Sprintf(ReportImBatchReplyCacheKey, midnight)
	batchReplyNum, err := global.GetRds().HLen(key).Result()
	if err != nil {
		global.Log.Errorf("IMREPORT InsertDB err:%v", err)
	}
	var chatStatistics models_report.ChatStatistics
	global.Report().Where("ctime = ?", midnight).First(&chatStatistics)
	sendTotalNum, desc := getDesc()
	chatStatistics.BatchReadNum = batchReadNum
	chatStatistics.BatchSendNum = batchSendNum
	chatStatistics.BatchReplyNum = batchReplyNum
	chatStatistics.Ctime = midnight
	chatStatistics.BatchSendToalNum = sendTotalNum
	chatStatistics.Desc = desc
	global.Log.Debugf("chatStatistics:%+v", chatStatistics)
	if chatStatistics.Id > 0 {
		err = global.Report().Updates(&chatStatistics).Error
	} else {
		err = global.Report().Create(&chatStatistics).Error
	}
	if err != nil {
		global.Log.Errorf("IMREPORT InsertDB err:%v", err)
		return err
	}

	return nil
}

func getDesc() (int64, string) {
	var cursor uint64
	var maxSendCount int64
	var desc string
	key := fmt.Sprintf(ReportImEveryTimeSendCachekey, timehelper.Midnight())
	var i int
	for {
		var err error
		var rs []string
		rs, cursor, err = global.GetRds().HScan(key, cursor, "", 1).Result()
		global.Log.Debugf("rs:%v,cursor:%v", rs, cursor)
		if err != nil || len(rs) < 1 {
			global.Log.Errorf("getDesc err:%v", err)
			break
		}
		for k, v := range rs {
			if k%2 != 0 {
				i++
				maxSendCount += cast.ToInt64(v)
				desc += fmt.Sprintf("第%v次:%v条", i, v)
			}
		}
		if cursor == 0 {
			break
		}
	}

	return maxSendCount, desc
}
